#include "ImageProcessor.h"
#include "aiprocess.h"
#include "configmanager.h"
#include "errordialogmanager.h"
#include "popupmanager.h"
#include "tools.h"

AIprocess &AIprocess::getInstance()
{
    static AIprocess _instance;
    return _instance;
}

QString AIprocess::extractModelName(const QString &modelPath) {
    // 正则表达式匹配模型名称的各个部分
    QRegExp regex(".*/(\\w+)_(\\w+)_(v\\d+\\.\\d+).rknn");


    if (regex.indexIn(modelPath) != -1) {
        QString part1 = regex.cap(1); // 提取第一个部分 Dual
        QString part2 = regex.cap(2); // 提取第二个部分 n
        QString part3 = regex.cap(3); // 提取版本号 V1.5

        QString name;
        if (part1 == "rw") {
            name = "入微";
            modelType_ = yoloModel;
        }else if (part1 == "dual") {
            name = "慧眼";
            modelType_ = yoloModel;
        }else if (part1 == "rl") {
            name = "智瞳";
            modelType_ = yoloModel;
        }else if (part1 == "hei") {
            name = "黑色";
            modelType_ = yoloModel;
        }else if (part1 == "bai") {
            name = "白色";
            modelType_ = PatchCoreModel;
        }
        emit modelTypeChange();
        if (part2 == "n") {
            name += "(速)";
        }else if(part2 == "m") {
            name += "(量)";
        }else if(part2 == "x") {
            name += "(霸)";
        }
        name += part3;

        return name;
    } else {
        return QString();
    }
}
//模型命名规则  s n m
//乾坤
void AIprocess::initialize(QString modlePath)
{

    if (modlePath.startsWith("files://")) {
        modlePath = modlePath.mid(8); // 去除 "file://"
    }
    ParamValue.setParameter("yoloDetection","modelPath",modlePath);
    QtConcurrent::run([this,modlePath]() {
        //QMutexLocker locker_ModelInit(&modelInitMutex_);
        LogDebug << "AIprocess Attemptting Initialize: "<< modlePath;
        PopupManager::instance().showPopup("正在导入算法模型", "正在导入"+modlePath);


        QMutexLocker locker(&modelMutex_);
        //先卸载模型
        patchCoreAi_.unloadModel();
        if(dualDetect_)
        {
            delete dualDetect_;
            dualDetect_ = nullptr;
            LogWarning << "AIprocess::Initialize Fail dualDetect_ has been init...";
            //return -1;
        }
        setIsInit(false);

        modelName_ = extractModelName(modlePath);
        LogDebug << "extractModelName from " << modlePath << "get:" << modelName_ << " modelType_:" << modelType_;
        emit modelNameChange();

        if(modelType_ == yoloModel)
        {
            if (modlePath.contains("rw")) {
                dualDetect_ = new DualDetect("master/test/logoV2_labels_list.txt" , 11);
                qDebug() << "The string contains 'rw'";
            } else {
                dualDetect_ = new DualDetect("master/test/coco_80_labels_list.txt" , 17);
                qDebug() << "The string does not contain 'rw'";
            }

            dualDetect_->setnmsThresh(ParamValue.getParameter<float>("yoloDetection", "nmsThreshold"));
            dualDetect_->setobjThresh(ParamValue.getParameter<float>("yoloDetection", "confidenceThreshold"));
            //qDebug() << "bjThreshChange" ;
            emit objThreshChanged();
            emit nmsThreshChange();
            //临时
            if(dualDetect_->loadModel(modlePath))
            {
                modelDataSize_ = dualDetect_->getmodelDataSize();
                emit modelDataSizeChange();
                modelInputSize_.clear();
                modelInputSize_ << dualDetect_->getimgWidth() <<
                    dualDetect_->getimgHeight() << dualDetect_->getimgChannel();
                emit modelInputSizeChange();
                SDKversion_ = QString(dualDetect_->getSDKversion());
                LogDebug << "finished load dualDetect_ SDKversion_" <<SDKversion_;
                emit SDKversionChange();
            }

            if(dualDetect_->modelLoaded)
            {
                setIsInit(true);
            }else
            {
                PopupManager::instance().hidePopup();
                ErrorDialogManager::instance().showNonBlockingInfo("模型导入",modelName_+" 导入成功");
                return ;
            }
            //QThread::sleep(5);
            PopupManager::instance().hidePopup();
            ErrorDialogManager::instance().showNonBlockingInfo("模型导入",modelName_+" 导入成功");
        }else if(modelType_ == PatchCoreModel){
            if(patchCoreAi_.initial() == 0 && patchCoreAi_.loadModel(modlePath))
            {
                modelDataSize_ = patchCoreAi_.getmodelDataSize();
                emit modelDataSizeChange();
                modelInputSize_.clear();
                modelInputSize_ <<  patchCoreAi_.getimgInputSize() <<
                    patchCoreAi_.getimgInputSize() << 3 ;
                emit modelInputSizeChange();
                emit modelDetalChange();
                SDKversion_ = QString(patchCoreAi_.getSDKversion());
                LogDebug << "SDKversion_" <<SDKversion_;
                emit SDKversionChange();
                emit canRunChange();
                emit imageInfoListChange();
                if(!patchCoreAi_.loadCoreSet())
                {
                    emit coreSetDetalChange();
                    PopupManager::instance().hidePopup();
                    ErrorDialogManager::instance().showNonBlockingError("知识库载入失败","检查知识库，尝试重新训练");
                    return;
                }
                setIsInit(true);
                emit coreSetDetalChange();
            }else
            {
                LogError << "Fail to load model" << modelName_;
                PopupManager::instance().hidePopup();
                ErrorDialogManager::instance().showNonBlockingError("模型导入失败",modelName_ + "导入失败");
                return ;
            }
            LogError << "successful to load model" << modelName_;
            PopupManager::instance().hidePopup();
            ErrorDialogManager::instance().showNonBlockingInfo("模型导入",modelName_+" 导入成功");
        }else
        {
            LogError << "not find modelType_:" << modelType_;
            PopupManager::instance().hidePopup();
            ErrorDialogManager::instance().showNonBlockingError("模型导入失败",modelName_+" 无效模型");
        }
    });

    return  ;
}

AIprocess::AIprocess(QObject *parent) : QObject(parent) ,
    modelType_(noneModel),
    isInit_(false),
    dualDetect_(nullptr)
{
    //dualDetect_ = new DualDetect();
    confidenceThreshold = ParamValue.getParameter("yoloDetection","confidenceThreshold").toFloat();
    nmsThreshold = ParamValue.getParameter("yoloDetection","nmsThreshold").toFloat();
    objThresh_ = ParamValue.getParameter<float>("yoloDetection", "confidenceThreshold");
    modelInputSize_ << 0 << 0<<0;
    modelDataSize_ = 0;
    SDKversion_ = "暂无模型";
    modelName_ = "请载入模型";

    //dualDetect_->setnmsThresh(nmsThreshold);
    //dualDetect_->setnmsThresh(confidenceThreshold);
    //dualDetect_->loadModel("master/test/best_rknnAfter.rknn");
    shieldAreaList_ = ParamValue.getParameter<QVariantList>("yoloDetection", "shieldAreaList");
    defectEnable_ = ParamValue.getParameter<QVariantMap>("yoloDetection","defectEnable");
    connect(&ConfigManager::getInstance() , &ConfigManager::valueTableLoad, this, &AIprocess::valueTableLoad);
    //Initialize();
}

void AIprocess::processImg(ImageRecord &imgcard)
{
    //QMutexLocker locker_ModelInit(&modelInitMutex_);
    bool isShield = false;
    QString outtext;
    outtext = "AI分析:\n";
    bool isDrawOutput = (ImageProcessor::getInstance().selectedStep()==ImageProcessor::MeauAi);

    LogTrack << "Starting AIprocess Img";
    cv::Mat img_src = imgcard.getStepImage(StepProcess::Reprogress);
    cv::Mat img_src_gray = imgcard.grayImagePre;
    cv::Mat img_base = imgcard.getbaseImage();
    cv::Mat img_src_draw = img_src.clone();
    //QMutexLocker locker(&modelMutex_);
    if( !isInit() )
    {
        outtext += "没有启动[未载入模型]\n";
        ImageProcessor::getInstance().setdetectDetail(outtext);
        LogError << "AAIprocess isnot Init";
        imgcard.setStepImage(StepProcess::Detect, img_src);
        //imgcard.setState(ImageRecord::Fail);
        imgcard.setStepImage(StepProcess::Detect, img_src_draw);
        imgcard.setDetectStepTime(Detect,outtext);
        return;
    }
    if (img_src.empty() || img_base.empty() || img_src_gray.empty()) {
        outtext += "分析失败[基准图为空]\n";
        ImageProcessor::getInstance().setdetectDetail(outtext);
        LogError << "AIprocess img_base ||img_src   image is empty";
        imgcard.setStepImage(StepProcess::Detect, img_src);
        //imgcard.setState(ImageRecord::Fail);
        imgcard.setStepImage(StepProcess::Detect, img_src_draw);
        imgcard.setDetectStepTime(Detect,outtext);
        return;
    }

    outtext += "输入图片尺寸:" + QString("[ %1 x %2] \n")
                                     .arg(img_src.size().width)
                                     .arg(img_src.size().height);

    if (aiRoi.empty() || aiRoi.width < 5 || aiRoi.height < 5)
    {
        aiRoi = cv::Rect(0 , 0,  img_src.cols , img_src.rows);
    }

    int roi_x = aiRoi.x;
    int roi_y = aiRoi.y;
    int roi_width = aiRoi.width;
    int roi_height = aiRoi.height;

    roi_x = std::max(0, roi_x);  // ROI 左上角的 x 坐标至少为 0
    roi_y = std::max(0, roi_y);  // ROI 左上角的 y 坐标至少为 0

    // 确保ROI的宽度和高度不会超出图像的右下角
    roi_width = std::min(roi_width, img_src.cols - roi_x);  // ROI 宽度不会超出图像右边界
    roi_height = std::min(roi_height, img_src.rows - roi_y);  // ROI 高度不会超出图像下边界

    // 创建修正后的ROI
    cv::Rect valid_roi(roi_x, roi_y, roi_width, roi_height);


    cv::Mat img_for_detect = img_src(valid_roi);
    QElapsedTimer timer;
    timer.start();
    object_detect_result_list od_results;
    {
        QMutexLocker locker(&modelMutex_);
        if(modelType_ == yoloModel)
        {
            if(dualDetect_ -> detect(img_base,img_for_detect,&od_results))
            {
                LogError << "detect fail";
            }
        }else if(modelType_ == PatchCoreModel)
        {
            if(patchCoreAi_.detect(img_for_detect,&od_results,objThresh()))
            {
                LogError << "detect fail";
            }
        }
    }

    for (int i = 0; i < od_results.count; ++i)
    {
        // 需要将检测结果的坐标转换到原图像中的坐标
        object_detect_result &result = od_results.results[i];
        result.box.left += valid_roi.x;
        result.box.top += valid_roi.y;
        result.box.right += valid_roi.x;
        result.box.bottom += valid_roi.y;
    }


    char text[1024];
    outtext += QString("AI分析完成 用时 %1 ms").arg(timer.elapsed());
    outtext += QString("当前检测阈值：%1").arg(objThresh());
    if(modelType_ == PatchCoreModel)
    {
        outtext += QString("[%1] \n").arg( patchCoreAi_.pred_score());
    }else {
        outtext += "\n" ;
    }
    outtext += QString("包含缺陷：%1 \n").arg(od_results.count);
    LogTrack << "get od_results.count :" <<od_results.count;

    if(shieldAreaList_.size() == 0 || modelType_ == PatchCoreModel)
    {
        isShield = true;
        outtext += QString("未使用屏蔽\n");
    }
    if(modelType_ == yoloModel)
    {
        for (int i = 0; i < od_results.count; i++)
        {
            object_detect_result *det_result = &(od_results.results[i]);
            LogTrack << "Attempting to isBoxInShieldAreaList2 "<<  det_result->cls_id;
            QString keyName = QString::fromUtf8(dualDetect_->getCocoClsToName((det_result->cls_id)));
            if (!defectEnable_.contains(keyName) || defectEnable_[keyName].toBool()==false) {
                //LogError << "find ["<<keyName<<"] but it not Enabel";
                continue;
            }

            if (!AIprocess::isBoxInShieldAreaList(shieldAreaList_, *det_result)) {
                if (det_result->cls_id == 1 && det_result->prop < get_dirtyThreshold()) {
                    continue;
                }

                int x1 = det_result->box.left;
                int y1 = det_result->box.top;
                int x2 = det_result->box.right;
                int y2 = det_result->box.bottom;

                if (get_dirtyGradThreshold() != 0 && get_dirtysize() != 0 &&
                    (det_result->cls_id == 1 || det_result->cls_id == 7))
                {
                    if((abs(y2 - y1 ) < get_dirtysize()) && (abs(x2 - x1) < get_dirtysize()) && !isDrawOutput)
                    {
                        continue;
                    }


                    int roi_x1 = std::max(0, x1);
                    int roi_y1 = std::max(0, y1);
                    int roi_x2 = std::min(img_src_gray.cols, x2);
                    int roi_y2 = std::min(img_src_gray.rows, y2);
                    qInfo() << "ROI Coordinates: (" << roi_x1 << ", " << roi_y1 << "), (" << roi_x2 << ", " << roi_y2 << ")";

                    // 获取ROI区域
                    cv::Mat suspiciousDirty = img_src_gray(cv::Rect(roi_x1, roi_y1, roi_x2 - roi_x1, roi_y2 - roi_y1));

                    // 二值化：以某个阈值将图像转化为黑白
                    cv::Mat binary;
                    int threshold = get_dirtyGradThreshold();
                    if(get_dirtyisWhite())
                        threshold = 255 - threshold;
                    cv::threshold(suspiciousDirty, binary, threshold , 255, cv::THRESH_BINARY);

                    if(get_dirtyisWhite())
                        cv::bitwise_not(binary, binary);  // 图像翻转
                    // 闭运算：首先膨胀，再腐蚀
                    cv::Mat closed;
                    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));  // 创建一个结构元素
                    cv::morphologyEx(binary, closed, cv::MORPH_CLOSE, kernel);  // 进行闭运算
                    qInfo() << "Closed operation completed";

                    // 找到闭运算后的最大连通区域
                    std::vector<std::vector<cv::Point>> contours;
                    std::vector<cv::Point> maxContours;
                    cv::findContours(closed, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
                    // 找到最大连通区域
                    double maxArea = 0;
                    cv::Rect largestRect;
                    for (const auto& contour : contours) {
                        cv::Rect boundingRect = cv::boundingRect(contour);
                        double area = boundingRect.area();
                        if (area > maxArea) {
                            maxContours = contour;
                            maxArea = area;
                            largestRect = boundingRect;
                        }
                    }

                    // 选择两个区域中面积较小的区域
                    cv::Rect finalRect = largestRect;
                    qInfo() << "Selected Rect: x=" << finalRect.x
                            << " y=" << finalRect.y
                            << " width=" << finalRect.width
                            << " height=" << finalRect.height;

                    // 评估区域的大小，绘制矩形框
                    if (isDrawOutput) {
                        int rectSize = get_dirtysize();
                        int rectX = roi_x1 + finalRect.x + finalRect.width / 2 - rectSize / 2;
                        int rectY = roi_y1 + finalRect.y + finalRect.height / 2 - rectSize / 2;

                        cv::Rect targetRect(rectX, rectY, rectSize, rectSize);
                        qInfo() << "Drawing rectangle at (" << rectX << ", " << rectY
                                << ") with size (" << rectSize << ", " << rectSize << ")";

                        // 根据最终的矩形决定颜色
                        if (finalRect.width < rectSize && finalRect.height < rectSize) {
                            qInfo() << "Rectangle color: Red";
                            cv::rectangle(img_src_draw, targetRect, cv::Scalar(0, 0, 255), 2);  // 红色矩形
                        } else {
                            qInfo() << "Rectangle color: Green";
                            cv::rectangle(img_src_draw, targetRect, cv::Scalar(0, 255, 0), 2);  // 绿色矩形
                        }

                        if(!maxContours.empty())
                        {
                            cv::Scalar fillColor(0, 125, 125);  // 填充颜色为绿色
                            std::vector<cv::Point> offsetContours;
                            for (const auto& pt : maxContours) {
                                offsetContours.push_back(cv::Point(pt.x + roi_x1, pt.y + roi_y1));
                            }
                            cv::drawContours(img_src_draw, std::vector<std::vector<cv::Point>>{offsetContours}, -1, cv::Scalar(0, 125, 125), 2);
                        }

                    }

                    // 如果选取的矩形小于目标尺寸，则跳过
                    if (finalRect.width < get_dirtysize() && finalRect.height < get_dirtysize()) {
                        qInfo() << "Skipping due to small bounding box";
                        continue;
                    }
                }



                sprintf(text, "%s, %.1f%%", dualDetect_->getCocoClsToName((det_result->cls_id)), det_result->prop * 100);
                imgcard.setDefect(9 + det_result->cls_id);

                rectangle(img_src_draw, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 0, 0, 255), 2);
                putText(img_src_draw, text, cv::Point(x1, y1 - 6), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 2);
                outtext += QString("缺陷：%1 {%2,%3,%4,%5} \n").arg(text)
                               .arg( det_result->box.left)
                               .arg( det_result->box.top )
                               .arg( det_result->box.right )
                               .arg( det_result->box.bottom);
            } else {
                QString temp_ = QString("已经屏蔽：[%1] {%2,%3,%4,%5} \n")
                                    .arg( dualDetect_->getCocoClsToName(det_result->cls_id))
                                    .arg( det_result->box.left)
                                    .arg( det_result->box.top )
                                    .arg( det_result->box.right )
                                    .arg( det_result->box.bottom);
                outtext += temp_;
                LogTrack <<temp_;
            }
        }
    }

    if(isDrawOutput){
        //绘制屏蔽框
        for (const auto &var : shieldAreaList_) {
            QVariantList item = var.toList();

            if (item.size() != 5) continue;
            int cls = item[0].toInt();
            int x = item[1].toInt();
            int y = item[2].toInt();
            int width = item[3].toInt();
            int height = item[4].toInt();
            drawDashedRectangle(img_src_draw, x, y, width, height, cls);
        }
        cv::rectangle(img_src_draw, valid_roi, cv::Scalar(0, 255, 0), 2);  // 在原图上绘制绿色框
        cv::Point startPoint(valid_roi.x, valid_roi.y); // 获取 valid_roi 左上角的坐标
        cv::Rect smallRect(startPoint, cv::Size(get_dirtysize(), get_dirtysize()));
        // 在原图上绘制该矩形，颜色为红色，线宽为 2
        cv::rectangle(img_src_draw, smallRect, cv::Scalar(0, 0, 255), 2);



        drawPolygonsOnImage(img_src_draw, polygonVariant_);

        ImageProcessor::getInstance().displayOKNGReson(imgcard.getNgCard());
        ImageProcessor::getInstance().setdetectDetail(outtext);
        if(modelType_ == yoloModel)
            ImageProvider::getInstance().image2qml(img_base,"Box1");
        else if(modelType_ == PatchCoreModel)
            ImageProvider::getInstance().image2qml(patchCoreAi_.outImage_,"Box1");
        ImageProvider::getInstance().image2qml(img_src,"Box2");
        ImageProvider::getInstance().image2qml(img_src_draw, "Main");
        imgcard.setIsSkipDisplay(true);
    }
    LogTrack << "AIprocess Succeesful";
    imgcard.setDetectStepTime(Detect,outtext);
    imgcard.setStepImage(StepProcess::Detect, img_src_draw);
    // static int i = 0;
    // if (od_results.count > 8) {
    //     i++;
    //     std::string filename = "./out" + std::to_string(i) + ".jpg";
    //     cv::imwrite(filename, img_src_draw);
    // }
}


bool AIprocess::isBoxInShieldAreaList(const QVariantList &shieldAreaList, const object_detect_result &det_result) {
    for (const auto &var : shieldAreaList) {
        // if (!var.canConvert<QVariantList>()) {
        //     continue; // 确保 var 是 QVariantList
        // }
        QVariantList item = var.toList();

        if (item.size() != 5) continue;

        int cls = item[0].toInt();
        int x = item[1].toInt()-20;
        int y = item[2].toInt()-20;
        int width = item[3].toInt()+40;
        int height = item[4].toInt()+40;

        int areaRight = x + width;
        int areaBottom = y + height;

        // LogTrack << "Class:" << cls;
        // LogTrack << "X:" << x;
        // LogTrack << "Y:" << y;
        // LogTrack << "Area Right:" << areaRight;
        // LogTrack << "Area Bottom:" << areaBottom;

        // LogTrack << "det_result.box:[" << det_result.cls_id <<"]"
        //          << "left:" << det_result.box.left
        //          << "right:" << det_result.box.right
        //          << "top:" << det_result.box.top
        //          << "bottom:" << det_result.box.bottom;
        // // qDebug << "Class:" << cls;
        // // qDebug << "X:" << x;
        // // qDebug << "Y:" << y;
        // // qDebug << "Width:" << width;
        // // qDebug << "Height:" << height;
        // // qDebug << "Area Right:" << areaRight;
        // // qDebug << "Area Bottom:" << areaBottom;

        if ((cls == det_result.cls_id || cls == -1) &&
            det_result.box.left >= x && det_result.box.right <= areaRight &&
            det_result.box.top >= y && det_result.box.bottom <= areaBottom) {
            return true;
        }
    }
    int i =  0 ;
    QList<QVariant> polygonDefects = polygonDefect();  // 假设这是你的 QList

    for (int i = 0; i < polygonDefects.size(); ++i) {
        int defectCls = polygonDefects[i].toInt();

        if (defectCls == det_result.cls_id || defectCls == -1)
        {
            int left = det_result.box.left;
            int top = det_result.box.top;
            int right = det_result.box.right;
            int bottom = det_result.box.bottom;

            bool isInside = isRectangleInPolygon(polygonVariant_.at(i), left, top, right, bottom);

            if (isInside) {
                return true;
            }
        }
    }
    return false;
}


void AIprocess::setIsInit(bool isInit)
{
    isInit_ = isInit;
    emit isInitChange();

}

float AIprocess::objThresh()
{
    // if(dualDetect_ == nullptr)
    // {
    //     LogWarning << "AIprocess::objThresh Fail dualDetect_ has been init...";
    //     return 0;
    // }
    return objThresh_;
}

void AIprocess::setobjThresh(float objThresh)
{
    {
        QMutexLocker locker(&modelMutex_);
        LogDebug << "Attempting to set setobjThresh : " << objThresh;

        if(modelType_ == yoloModel)
        {
            qInfo() << "go in setobjThresh 1";
            if(!dualDetect_)
            {
                ErrorDialogManager::instance().showNonBlockingError("AI设置失败", "请先打开模型");
                LogWarning << "AIprocess::setobjThresh Fail dualDetect_ has been init...";
                return;
            }
            dualDetect_->setobjThresh(objThresh);
        }
        if (objThresh_!= objThresh)
            objThresh_ = objThresh;
        qInfo() << "go in setobjThresh 2";
        ParamValue.setParameter("yoloDetection", "confidenceThreshold",objThresh);
        qInfo() << "go in setobjThresh 3";
    }
    emit objThreshChanged();
}

float AIprocess::nmsThresh()
{
    QMutexLocker locker(&modelMutex_);
    if(!dualDetect_)
    {
        LogWarning << "AIprocess::nmsThresh Fail dualDetect_ has been init...";
        return 0;
    }
    return dualDetect_->getnmsThresh();
}

void AIprocess::setnmsThresh(float nmsThresh)
{
    QMutexLocker locker(&modelMutex_);
    LogDebug << "Attempting to set setnmsThresh" << nmsThresh;
    if(!dualDetect_)
    {
        ErrorDialogManager::instance().showNonBlockingError("AI设置失败", "请先打开模型");
        LogWarning << "AIprocess::setnmsThresh Fail dualDetect_ has been init...";
        return ;
    }
    ParamValue.setParameter("yoloDetection", "nmsThreshold",nmsThresh);
    dualDetect_->setnmsThresh(nmsThresh);
}

void AIprocess::setdefectEnable(QVariantMap defectEnable)
{
    QMutexLocker locker(&modelMutex_);
    LogDebug << "AIprocess::setdefectEnable :" << defectEnable;
    if (defectEnable != defectEnable_){
        defectEnable_ = defectEnable;
        emit defectEnableChange();
    }
}

void AIprocess::addshieldAreaList(int defect, int x, int y, int wid, int hei)
{
    QVariantList shieldArea;
    shieldArea << defect << x << y << wid << hei;

    // 调试语句跟踪值
    QVariantList shieldAreaVariantList = shieldAreaList_;
    shieldAreaVariantList.append(QVariant::fromValue(shieldArea));
    ParamValue.setParameter("yoloDetection", "shieldAreaList", shieldAreaVariantList);

    // 更新 shieldAreaList_
    shieldAreaList_ = shieldAreaVariantList;

    // 调试语句跟踪更新后的列表
    qDebug() << "defect:" << defect
             <<"Qvariant :" << QVariant::fromValue(shieldAreaList_);;

    emit shieldAreaListChange();
}

void AIprocess::addshieldimutant(int defect, QVariantList Area)
{
    QVector<QPointF> points;
    qDebug() << "addshieldimutant:" << Area;
    for (const auto &item : Area) {
        QVariantMap pointMap = item.toMap();
        if (pointMap.contains("x") && pointMap.contains("y")) {
            qreal x = pointMap["x"].toReal();
            qreal y = pointMap["y"].toReal();
            points.append(QPointF(x, y));
        }
    }

    // 判断是否封闭
    if (!areaisClosed(points)) {
        // 如果未封闭，添加起点和终点连接形成闭环
        points.append(points.first());
    }

    QPolygonF boundingPolygon = areaconvexHull(points);

    polygonVariant_.append(boundingPolygon);
    QVariantList temp = polygonDefect();
    temp.append(defect);
    LogInfo<< "Attempting to shieldimutant add temp" << temp;
    setpolygonDefect(temp);
}


void AIprocess::delshieldimutant(int index)
{
    LogInfo<< "Attempting to delshieldimutant" << index;
    polygonVariant_.removeAt(index);
    QVariantList temp = polygonDefect();
    temp.removeAt(index);
    setpolygonDefect(temp);

}
void AIprocess::loadCoreSet()
{
    if(patchCoreAi_.loadCoreSet())
        setIsInit(true);
    emit coreSetDetalChange();
}

void AIprocess::addTrainImage()
{
    LogDebug << "Attempting to AIprocess::addTrainImage()";
    patchCoreAi_.addTrainImage(ImageProcessor::getInstance().imgCardsLast.getStepImage(Reprogress));
    LogDebug << "patchCoreAi_.imageInfoList()" << patchCoreAi_.imageInfoList;
    emit imageInfoListChange();
}

void AIprocess::delTrainImage(int index)
{
    LogDebug << "Attempting to delTrainImage: " << index;
    patchCoreAi_.delTrainImage(index);
    emit imageInfoListChange();
}

void AIprocess::clearTrainImage()
{
    LogDebug << "Attempting to AIprocess::clearTrainImage()";
    patchCoreAi_.clearTrainImage();
    emit imageInfoListChange();
    ErrorDialogManager::instance().showNonBlockingInfo("清空完成","请重新添加图片开始训练");

}

void AIprocess::autoTrain()
{
    isTrain =true;
    QtConcurrent::run([this]() {
        LogDebug << "AIprocess Attemptting autoTrain ";
        emit startTrain();
        if(isTrain && patchCoreAi_.pre_training())
            goto errorReturn ;
        if(isTrain && patchCoreAi_.load_training_data())
            goto errorReturn ;
        if(isTrain && patchCoreAi_.start_training())
            goto errorReturn ;
        emit alreadyTrain();
        emit currentScheduleChange();
        while(isTrain && patchCoreAi_.currentSchedule <= 1)
        {
            if(patchCoreAi_.continue_iteration() == -1 || isTrain==false)
                goto errorReturn ;
            emit currentScheduleChange();
        }
        patchCoreAi_.quit_training();
        emit currentScheduleChange();
        LogDebug << "sucessful to AIprocess::autoTrain";
        emit finishTrain();
        ErrorDialogManager::instance().showNonBlockingInfo("训练完成", "载入知识库开始");
        return;
    errorReturn:
        ErrorDialogManager::instance().showNonBlockingInfo("训练结束", "发生训练故障或主动取消");
        patchCoreAi_.quit_training();
        LogDebug << "Fail to AIprocess::autoTrain";
        emit finishTrain();
        return ;
    });
}

void AIprocess::stopTrain(){
    LogDebug << "Attemping to stopTrain";
    isTrain =false;

}

void AIprocess::delshieldAreaList(int index)
{
    if (index >= 0 && index < shieldAreaList_.size()) {
        shieldAreaList_.removeAt(index);
    } else {
        LogWarning << "Index out of range.";
        ErrorDialogManager::instance().showNonBlockingError("设置屏蔽区域失败","超出设置范围");
    }
    emit shieldAreaListChange();
}


void AIprocess::configDataChanged(QString Category, QString key)
{
    QMutexLocker locker(&modelMutex_);
    if(Category == "yoloDetection" && key == "nmsThreshold")
    {
        dualDetect_->setnmsThresh(ConfigManager::getInstance().getParameter("yoloDetection","nmsThreshold").toFloat());
    }
    else if(Category == "yoloDetection" && key == "confidenceThreshold")
    {
        dualDetect_->setobjThresh(ConfigManager::getInstance().getParameter("yoloDetection","confidenceThreshold").toFloat());
    }

}

void AIprocess::valueTableLoad()
{
    LogDebug << "Attempting to AIprocess::valueTableLoad";
    shieldAreaList_ = ParamValue.getParameter<QVariantList>("yoloDetection", "shieldAreaList");

    qDebug() << "value shieldAreaList_:" <<shieldAreaList_;
    defectEnable_ = ParamValue.getParameter<QVariantMap>("yoloDetection","defectEnable");
    emit defectEnableChange();
    emit shieldAreaListChange();
    initialize(ParamValue.getParameter<QString>("yoloDetection", "modelPath"));
}
void AIprocess::setAIroi(int x, int y, int wid, int hei)
{
    qInfo() << "  AIprocess::setAIroi x :" << x
            << "y:" << y << "wid:"
            << wid << "hei:" << hei;
    if(wid < 20 || hei < 20)
    {
        LogError << "Fail to AIprocess::setAIroi width:" ;
        ErrorDialogManager::instance().showNonBlockingError("设置AI roi错误", "尺寸太小");
        return;
    }
    aiRoi = cv::Rect(x,y,wid,hei);
}

void AIprocess::resetAIroi()
{
    aiRoi = cv::Rect2d();
}


int testAIprocess()
{
    // DualDetect dualDetect;
    // cv::Mat  base_img= cv::imread("master/test/base.jpg");
    // cv::Mat  test_img = cv::imread("master/test/test.jpg");
    // dualDetect.loadModel("master/test/best_rknnAfter.rknn");
    // object_detect_result_list od_results;
    // LogDebug << "base_img: " << base_img.size;
    // LogDebug << "test_img: " << test_img.size;
    // if(dualDetect.detect(base_img,test_img,&od_results))
    // {
    //     LogError << "detect fail";
    // }
    // char text[256];
    // LogTrack << "get od_results.count :" <<od_results.count;
    // for (int i = 0; i < od_results.count; i++)
    // {
    //     LogDebug << "goin" <<od_results.count;
    //     object_detect_result *det_result = &(od_results.results[i]);
    //     // LogDebug << "goin2" ;
    //     printf("%s @ (%d %d %d %d) %.3f\n", dualDetect.getCocoClsToName(det_result->cls_id),
    //            det_result->box.left, det_result->box.top,
    //            det_result->box.right, det_result->box.bottom,
    //            det_result->prop);
    //     sprintf(text, "%s %.1f%%",  dualDetect.getCocoClsToName((det_result->cls_id)), det_result->prop * 100);
    //     int x1 = det_result->box.left;
    //     int y1 = det_result->box.top;
    //     int x2 = det_result->box.right;
    //     int y2 = det_result->box.bottom;

    //     rectangle(test_img, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 0, 0, 255), 2);
    //     putText(test_img, text, cv::Point(x1, y1 - 6), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 2);
    // }
    // cv::imwrite("./out.jpg", test_img);
    // return 0;
}






